#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266WiFi.h>

/*
static const uint8_t D0   = 16; LED1
static const uint8_t D1   = 5;
static const uint8_t D2   = 4;
static const uint8_t D3   = 0;
static const uint8_t D4   = 2;  LED2
static const uint8_t D5   = 14;
static const uint8_t D6   = 12;
static const uint8_t D7   = 13;
static const uint8_t D8   = 15;
static const uint8_t D9   = 3; rx
static const uint8_t D10  = 1; tx

 */
#define powerD D1
#define powerPulldown D2
#define resetD D6
int powerBTN = 0;
#define volt5D D7
#define hddD D8

const char* t_p = "text/plain";
const char* ssid = "zsha";
const char* password = "920662zsh";
uint8_t mac[] = {0x2c,0x3a,0xe8,0x06,0xb9,0x37};//192.168.1.50
ESP8266WebServer server(80);

void handleRoot() {
  server.send(200, "text/html", "<html></html>");
}

static const char mainpage[] PROGMEM = "\
<html>\r\n\
return:<input id='J_read' type='text' style='width:250px' value=''><br/>\r\n\
<input id='J_Pon' type='button' style='height:70px' value='_____Power on_____'> \r\n\
<input id='J_Poff' type='button' style='height:70px' value='_____Power off_____'> \r\n\
<input id='J_Pbtn' type='button' style='height:70px' value='_____Power btn_____'> \r\n\
<input id='J_S' type='button' style='height:70px' value='_____Status_______'><br/>\r\n\
<textarea id='texta' style='width:500px;height:300px;'></textarea><br/><br/>\r\n\
<input id='cmd' type='text' style='width:300px' value=''><br/><br/>\r\n\
<input id='J_send' type='button' style='height:30px' value='send'/> \r\n\
<input id='J_receive' type='button' style='height:30px' value='receive'> \r\n\
<input id='J_clear' type='button' style='height:30px' value='clear'><br/><br/>\r\n\
<input id='ctrl_c' type='button' value='^c'> \r\n\
<input id='ctrl_x' type='button' value='^x'> \r\n\
<input id='tab' type='button' value='tab'> \r\n\
<input id='up' type='button' value='up'> \r\n\
<input id='down' type='button' value='down'> \r\n\
<input id='left' type='button' value='left'> \r\n\
<input id='right' type='button' value='right'> \r\n\
<input id='esc' type='button' value='esc'> \r\n\
<input id='f1' type='button' value='f1'> \r\n\
<input id='f2' type='button' value='f2'> \r\n\
<input id='f3' type='button' value='f3'> \r\n\
<input id='f4' type='button' value='f4'> \r\n\
<input id='pageup' type='button' value='pu'> \r\n\
<input id='pagedown' type='button' value='pd'> \r\n\
<input id='backspace' type='button' value='bs'> \r\n\
<input id='del' type='button' value='del'> \r\n\
<br/><br/>\r\n\
<script src='base.js' ></script>\r\n\
<script>\r\n\
	var calling = false;\r\n\
	var texta = JQ('texta');\r\n\
	var cmd = JQ('cmd');\r\n\
	JQ('J_Pon').onclick=async ()=>{\r\n\
		var data = await ajaxGet('/power_on','');\r\n\
		JQ('J_read').value = data;\r\n\
	};\r\n\
	JQ('J_Poff').onclick=async ()=>{\r\n\
		var data = await ajaxGet('/power_off','');\r\n\
		JQ('J_read').value = data;\r\n\
	};\r\n\
	JQ('J_Pbtn').onclick=async ()=>{\r\n\
		var data = await ajaxGet('/power_btn','');\r\n\
		JQ('J_read').value = data;\r\n\
	};\r\n\
	JQ('J_S').onclick=async ()=>{\r\n\
		var data = await ajaxGet('/status','');\r\n\
		JQ('J_read').value = data;\r\n\
	};\r\n\
	var send = async ()=>{\r\n\
		calling = true;\r\n\
		await ajaxGet('/tomcu',cmd.value);\r\n\
		cmd.value = '';\r\n\
		calling = false;\r\n\
	};\r\n\
	JQ('J_send').onclick=send;\r\n\
	cmd.onkeydown = (e)=>{\r\n\
		if(e.key=='Enter'){\r\n\
			send();\r\n\
		}\r\n\
	};\r\n\
	JQ('J_clear').onclick=()=>{\r\n\
	 texta.value = '';calling = false;\r\n\
	};\r\n\
	var receive = async ()=>{\r\n\
		if(calling)return;\r\n\
		calling = true;\r\n\
		while(true){\r\n\
			var data = await ajaxGet('/count','');\r\n\
			var count = parseInt(data);\r\n\
			if(count==0)break;\r\n\
			var content = await ajaxGet('/frommcu','');\r\n\
			texta.value = texta.value + content;\r\n\
		};\r\n\
		calling = false;\r\n\
	};\r\n\
	setInterval(receive, 1000);\r\n\
	JQ('J_receive').onclick=function(){\r\n\
		receive();\r\n\
	};\r\n\
	\r\n\
	var special = async (num)=>{\r\n\
		await ajaxGet('/special',''+num);\r\n\
		JQ('J_read').value = ''+num;\r\n\
	};\r\n\
JQ('ctrl_c').onclick=()=>{special(0)};\r\n\
JQ('ctrl_x').onclick=()=>{special(1)};\r\n\
JQ('tab').onclick=()=>{special(2)};\r\n\
JQ('up').onclick=()=>{special(3)};\r\n\
JQ('down').onclick=()=>{special(4)};\r\n\
JQ('left').onclick=()=>{special(5)};\r\n\
JQ('right').onclick=()=>{special(6)};\r\n\
JQ('esc').onclick=()=>{special(7)};\r\n\
JQ('f1').onclick=()=>{special(8)};\r\n\
JQ('f2').onclick=()=>{special(9)};\r\n\
JQ('f3').onclick=()=>{special('a')};\r\n\
JQ('f4').onclick=()=>{special('b')};\r\n\
JQ('pageup').onclick=()=>{special('c')};\r\n\
JQ('pagedown').onclick=()=>{special('d')};\r\n\
JQ('backspace').onclick=()=>{special('e')};\r\n\
JQ('del').onclick=()=>{special('f')};\r\n\
\r\n\
	\r\n\
</script>\r\n\
end</html>\r\n\
";

static const char basejsc[] PROGMEM = "\
function getxhr() {\r\n\
	var a=false;\r\n\
	try{\r\n\
		a=new ActiveXObject('Msxml2.XMLHTTP');\r\n\
	}catch (e){\r\n\
		try{\r\n\
			a=new ActiveXObject('Microsoft.XMLHTTP');\r\n\
		}catch (e2){\r\n\
			a = false;\r\n\
		}\r\n\
	}\r\n\
	if (!a && typeof XMLHttpRequest != 'undefined'){\r\n\
		a = new XMLHttpRequest();\r\n\
	}\r\n\
	return a;\r\n\
}\r\n\
\r\n\
var xhr = getxhr();\r\n\
\r\n\
function _ajaxGet(url,cont,cb) {\r\n\
	xhr.open('POST',url,true);\r\n\
	xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');\r\n\
	xhr.setRequestHeader('If-Modified-Since', '0');\r\n\
	xhr.onreadystatechange=()=>{\r\n\
		if(xhr.readyState==4){\r\n\
			if(xhr.status==200){\r\n\
				var res = xhr.responseText;\r\n\
				cb(res);\r\n\
			}\r\n\
		}\r\n\
	};\r\n\
	xhr.send(cont);\r\n\
}\r\n\
\r\n\
function ajaxGet(url,cont){\r\n\
 return new Promise((resolve, reject)=>{\r\n\
  _ajaxGet(url,cont,(data)=>{resolve(data);});\r\n\
 });\r\n\
};\r\n\
\r\n\
var JQ = function(id){\r\n\
	return document.getElementById(id);\r\n\
};\r\n\
";

char sendBuff1[64];
void handlePage() {

	server.chunkedResponseModeStart(200, "text/html");
	for(int i=0;i<sizeof(mainpage);i+=64){
		int size = sizeof(mainpage) - 1 - i;
		if(size>64)size=64;
		memcpy_P(sendBuff1, &mainpage[i], size);
		server.sendContent(sendBuff1, size);
	}
	server.chunkedResponseFinalize();
	
}

void basejs() {
	server.chunkedResponseModeStart(200, "text/html");
	for(int i=0;i<sizeof(basejsc);i+=64){
		int size = sizeof(basejsc) - 1 - i;
		if(size>64)size=64;
		memcpy_P(sendBuff1, &basejsc[i], size);
		server.sendContent(sendBuff1, size);
	}
	server.chunkedResponseFinalize();
}

volatile unsigned long currentMillisTime = 0;
volatile int V1 = 0;
volatile int V2 = 0;

volatile int _V1 = 0;
volatile int _V2 = 0;

volatile int isonP = 0;
volatile unsigned long currentMillisP = 0;

void _power_on() {
  digitalWrite(powerD, 1);
  powerBTN = 1;
  String ret = "ok";
  server.send(200, t_p, ret);
}

void _power_off() {
  digitalWrite(powerD, 0);
  powerBTN = 0;
  String ret = "ok";
  server.send(200, t_p, ret);
}
void _power_btn() {
  pinMode(powerPulldown, OUTPUT);
  isonP = 1;
  currentMillisP = millis();
  String ret = "ok";
  server.send(200, t_p, ret);
}

volatile int isonPL = 0;
volatile unsigned long currentMillisPL = 0;

void _longpower() {
  String ret = "ok";
  server.send(200, t_p, ret);
}

volatile int isonR = 0;
volatile unsigned long currentMillisR = 0;

void _reset() {
  digitalWrite(resetD, 1);
  isonR = 1;
  currentMillisR = millis();
  String ret = "ok";
  server.send(200, t_p, ret);
}

void _status() {
  //int v = digitalRead(volt5D);
  String ret = "ok ";
  ret += powerBTN == 1 ? "PWR on " : "PWR off ";
  //float vv1 = _V1;
  //float vv2 = _V2;
  //vv1 = (vv1*100/(vv1+vv2));
  //ret += "HDD :";
  //ret += vv1;//  _V1; // hdd on     _V2;//hdd off

  server.send(200, t_p, ret);
}

void handleNotFound() {
  server.send(404, t_p, "File Not Found");
}


char buffer[32768];
int readp = 0;
int writep = 0;


void _count() {
	String ret = "";
	int cnt = writep - readp;
	cnt = cnt & 32767;
	
	ret += cnt;

	server.send(200, t_p, ret);
}

void _tomcu() {
  String s = server.arg("plain");
  Serial.print(s);
  Serial.print("\n");
  String ret = "ok";
  server.send(200, t_p, ret);
}

void _special(){
  String s = server.arg("plain");
  char c = s[0];
  char* dat = "\n\0";
  switch(c){
	  case '0': dat = "\x03\0";//ctrl-c 03
	  case '1': dat = "\x18\0";//ctrl-x 18
	  case '2': dat = "\x09\0";//tab 09
	  case '3': dat = "\x1b\x5b\x41\0";//up 1b 5b 41
	  case '4': dat = "\x1b\x5b\x42\0";//down 1b 5b 42
	  case '5': dat = "\x1b\x5b\x44\0";//left 1b 5b 44
	  case '6': dat = "\x1b\x5b\x43\0";//right 1b 5b 43
	  case '7': dat = "\x1b\0";//esc 1b
	  case '8': dat = "\xf1\x1b\x5b\x31\x31\x7e\0";//f1 1b 5b 31 31 7e
	  case '9': dat = "\xf2\x1b\x5b\x31\x32\x7e\0";//f2 1b 5b 31 32 7e
	  case 'a': dat = "\xf3\x1b\x5b\x31\x33\x7e\0";//f3 1b 5b 31 33 7e
	  case 'b': dat = "\xf4\x1b\x5b\x31\x34\x7e\0";//f4 1b 5b 31 34 7e
	  case 'c': dat = "\x1b\x5b\x35\x7e\0";//pageup 1b 5b 35 7e
	  case 'd': dat = "\x1b\x5b\x36\x7e\0";//pagedown 1b 5b 36 7e
	  case 'e': dat = "\x7f\0";//backspace 7f
	  case 'f': dat = "\x1b\x5b\x33\x7e\0";//del 1b 5b 33 7e
  }
  Serial.print(dat);
  String ret = "ok";
  server.send(200, t_p, ret);
}

void _frommcu() {
	if(readp!=writep){
		server.chunkedResponseModeStart(200, t_p);
		while(1){
			int size = 0;
			for (int i = 0; i < 64; i++) {
				if(readp==writep){
					break;
				}
				sendBuff1[size] = buffer[readp];
				size++;
				readp++;
				readp&=32767;
			}
			if(size==0)break;
			server.sendContent(sendBuff1, size);
		}
		server.chunkedResponseFinalize();
	}else{
		server.send(200, t_p, "");
	}
}



//uint8_t mac[] = {0x2c,0x3a,0xe8,0x06,0xb9,0x38};
void setup(void) {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  //Serial.println("poweron");

  wifi_set_macaddr(STATION_IF, mac);
  
  digitalWrite(D4, 0);
  pinMode(D4, OUTPUT);
  
  pinMode(powerPulldown, INPUT);
  digitalWrite(powerPulldown, 0);
  
  
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(300);
    digitalWrite(D4, 1);
    delay(200);
    digitalWrite(D4, 0);
    //Serial.print(".");
  }
  
  //Serial.println("");
  //Serial.print("To:");
  //Serial.println(ssid);
  //Serial.print("IP:");
  //Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.on("/main", handlePage);
  server.on("/base.js", basejs);
  
  
  server.on("/power_on", _power_on);
  server.on("/power_off", _power_off);
  server.on("/power_btn", _power_btn);
  
  server.on("/longpower", _longpower);
  server.on("/reset", _reset);
  server.on("/status", _status);
  server.on("/tomcu", _tomcu);
  server.on("/special", _special);
  server.on("/frommcu", _frommcu);
  server.on("/count", _count);

  server.onNotFound(handleNotFound);

  server.begin();
  
  digitalWrite(powerD, 0);
  digitalWrite(resetD, 0);
  pinMode(powerD, OUTPUT);
  pinMode(resetD, OUTPUT);
  
  digitalWrite(D0, 0);
  pinMode(D0, OUTPUT);

  //Serial.println("started");
}
int tick = 0;

void loop(void) {
  server.handleClient();
  unsigned long mills = millis();
  int bytes = Serial.available();
  if(bytes>0){
	  int i;
	  for(int i=0;i<bytes;i++){
		  buffer[writep] = Serial.read();
		  writep++;
		  writep&=32767;
	  }
  }
  
  int v = digitalRead(hddD);
  if(v){
    V2++;
  }else{
    V1++;
  }
  
  if(mills - currentMillisTime > 1000){
    currentMillisTime = mills;
    if(WiFi.status() != WL_CONNECTED){
	  digitalWrite(D4, 1);
    }else{
	  digitalWrite(D4, 0);
    }
    if(tick==0){
      tick = 1;
	  digitalWrite(D0, 1);
    }
    else
    {
	  tick = 0;
	  digitalWrite(D0, 0);
    }
    _V1 = V1;
    _V2 = V2;
    V1 = 0;
    V2 = 0;
  }
  if(isonP){
    if(mills - currentMillisP > 200){
      pinMode(powerPulldown, INPUT);
      isonP = 0;
    }
  }
  /*
  
   if(isonPL){
    if(mills - currentMillisPL > 5000){
      digitalWrite(powerD, 0);
      isonPL = 0;
    }
  }

  if(isonR){
    if(mills - currentMillisR > 200){
      digitalWrite(resetD, 0);
      isonR = 0;
    }
  }
  */
  
}
